#!/usr/bin/env bash
#-------------------------------------------------
# 服务端相关开发工具
#-------------------------------------------------
## 编译指定模块 内部调用

DOC[srv_make]="编译源码"
fun_srv_make(){
    start_time=$(date +%s)
    # 编译server
    INFO "正在编译服务端源码"
    cd ${ROOT}/server/
    mkdir -p ebin
    paths=$(find src -type d | awk '{print "        ,'\''"$0"/*'\''" }')
    cat > Emakefile <<EOF
{
	[
	  './*'
${paths}
	]
	,[
		{hipe, [o3]}
		,debug_info
		,{i, "inc"}
		,{outdir, "ebin"}

        | [${ERL_MAKE_PARAM}]
	]
}.
EOF
    ${ERL} -noshell -make
    rm -f $lock # 解锁
    INFO "编译服务端源码完成:$(expr `date +%s` - $start_time)"
}


DOC[srv_start]="启动游戏服务器，参数:[平台标识] [区号]"
fun_srv_start(){
    declare -A cfg
    check_node_cfg $@
    if [ ! -d ${cfg[root]}/dets ]; then
        ERR "节点\e[92m${cfg[nodename]}\e[0;0m似乎没有安装，无法启动"
        exit 1
    fi
    cd ${cfg[root]}
    if $(in_cygwin); then
        ${WERL} -kernel inet_dist_listen_min ${ERL_PORT_MIN} -kernel inet_dist_listen_max ${ERL_PORT_MAX} +P 204800 +K true -smp enable -hidden +sbwt none -pa ${cfg[code_path]}/server/ebin -name ${cfg[nodename]} -s main start -extra ${cfg[type]} &
    else
        if is_screen_exists ${cfg[nodename]}; then
            if has_tty; then
                read -p "[93m=> 节点[92m${cfg[nodename]}[93m在之前已经启动，现在是否直接进入控制台?[0;0m [y/n]" choice
                if [[ $choice =~ y|Y|yes ]]; then
                    screen -r ${cfg[nodename]}
                fi
                exit 0
            else
                INFO "节点[92m${cfg[nodename]}[0;0m在之前已经启动"
            fi
        else
            start_file=${cfg[root]}/start.sh
            CMD="${ERL} -kernel inet_dist_listen_min ${ERL_PORT_MIN} -kernel inet_dist_listen_max ${ERL_PORT_MAX} +P 204800 +K true -smp enable -hidden  +sbwt none -pa ${ROOT}/server/ebin -name ${cfg[nodename]} -s main start -extra ${cfg[type]}"
            cat > ${start_file} <<EOF
#!/bin/bash
cd ${cfg[root]}
ulimit -SHn 102400
${CMD}
EOF
            chmod +x ${start_file}
            screen -dmSL ${cfg[nodename]} -s ${start_file}
            if has_tty; then
                echo "----------------------------------------------------------------------------------------------"
                INFO "节点\e[92m${cfg[nodename]}\e[0;0m正在启动中，启动完成后会直接进入控制台，操作时请注意(\e[92mctrl+a d\e[0;0m退出)。"
                echo "----------------------------------------------------------------------------------------------"
                if [ "$3" = "false" ]; then
                    exit 0;
                else
                    fun_srv_shell $@
                fi
            else
                INFO "节点\e[92m${cfg[nodename]}\e[0;0m正在启动中，如果想要了解启动结果，请查看服务器日志"
            fi
        fi
    fi
}


DOC[srv_stop]="关闭游戏服务器，参数:[平台标识] [区号]"
fun_srv_stop(){
    if $(in_cygwin); then
        ERR "cygwin下不支持此命令"
        exit
    fi

    declare -A cfg
    check_node_cfg $@
    if [ ! -d ${cfg[root]}/dets ]; then
        ERR "节点\e[92m${cfg[nodename]}\e[0;0m似乎没有安装，无法执行关闭操作"
        exit 1
    fi
    if ! is_screen_exists ${cfg[nodename]}; then
        ERR "节点\e[92m${cfg[nodename]}\e[0;0m似乎没有启动"
        exit 1
    fi
    # 检查锁
    lock=/tmp/stop_${cfg['platform']}_${cfg['zone_id']}.lock
    if [ -f $lock ]; then
        ERR "节点\e[92m${cfg['nodename']}\e[0,0m上有另一个关闭操作正在执行中，需等待该操作完成:$lock"
        exit 1
    fi
    touch $lock # 加锁
    cd ${cfg[root]}
    INFO "正在关闭节点\e[92m${cfg[nodename]}\e[0;0m..."
    ${ERL} -noshell -kernel inet_dist_listen_min ${ERL_PORT_MIN} -kernel inet_dist_listen_max ${ERL_PORT_MAX} -hidden -pa ${cfg[code_path]}/server/ebin -name stop_${cfg[nodename]} -setcookie ${cfg[cookie]} -eval "io:setopts([{encoding,unicode}]), main:stop_shell()" -s c q -extra ${cfg[nodename]}
    rm -f $lock # 解锁
    if [ $(ps aux|grep ${GAME_CODE}_${cfg['platform']}_${cfg['zone_id']} | grep -v grep | wc -l) -gt 0 ]; then
        ps aux|grep ${GAME_CODE}_${cfg['platform']}_${cfg['zone_id']} | grep -v grep| awk '{print $2}' | xargs kill
    fi
}



DOC[srv_install]="安装游戏节点，参数:[平台标识] [区号(0区表示中央服节点)]"
fun_srv_install(){
    declare -A cfg
    check_node_cfg $@ # 检查并补全节点配置信息
    if [ -e ${cfg[root]} ]; then
        ERR "目标路径\e[92m${cfg[root]}\e[0;0m非空，无法执行安装过程"
        exit 1
    fi

    INFO "\e[93m准备安装游戏节点，请确认以下信息:\e[0;0m"
    INFO "  节点名称: \e[92m${cfg[nodename]}\e[0;0m"
    INFO "  安装路径: \e[92m${cfg[root]}\e[0;0m"
    INFO "  节点类型: \e[92m${cfg[type]}\e[0;0m"
    INFO "      域名: \e[92m${cfg[host]}\e[0;0m"
    INFO "      端口: \e[92m${cfg[port]}\e[0;0m"
    INFO "数据库地址: \e[92m${cfg[db_host]}\e[0;0m"
    INFO "数据库名称: \e[92m${cfg[db_name]}\e[0;0m"
    read -p "[93m=> 是否继续？[0;0m[y/n]" choice
    if [[ $choice != y ]]; then
        exit 0
    fi

    mkdir -p ${cfg[root]} && cd ${cfg[root]}

    INFO "正在处理配置文件..."
    # 处理模板
    tpls=('env_zone.cfg' 'zone.sql' 'main.app' 'emysql.app')
    for v in ${tpls[*]};do
        file="${ROOT}/server/src/tpl/${v}"
        if [ ! -e $file ]; then
            ERR "找不到模板文件: ${file}"
            exit 1
        fi
        # 替换模板变量
        lines=$(<"${file}")
        for k in ${!cfg[@]}; do
            lines=${lines//\{\{$k\}\}/${cfg[$k]}}
        done
        lines=${lines//\v1\/server/server}
        lines=${lines//\v1\/web/web}
        # 替换空变量并生成文件
        echo "${lines}" | sed -e "s/{{.*}}//" > ${v}
    done

    INFO "正在创建数据库..."
    export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -e"create database ${cfg['db_name']}"
    # -p${cfg['db_pass']}
    if [ $? -ne 0 ]; then
        ERR "创建数据库时发生异常"
        exit 1
    fi

    INFO "正在导入数据库结构..."
    export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -e"source ${cfg[root]}/zone.sql"
    if [ $? -ne 0 ]; then
        ERR "导入数据库表结构时发生异常"
        exit 1
    fi

    INFO "正在建立目录和文件..."
    mkdir -p dets var/sess log/pack log_file face/${cfg['platform']}_${cfg['zone_id']} replay/${cfg['platform']}_${cfg['zone_id']} replay_share/${cfg['platform']}_${cfg['zone_id']}
    mv env_zone.cfg env.cfg
    ln -s ${ROOT}/web/www .
    ln -s ${ROOT}/server/srv.sh .
    rm -f zone.sql
    chmod -R 777 ${cfg['root']}/var
    INFO "节点安装完成"
}

DOC[srv_uninstall]="删除游戏节点，参数:[平台标识] [区号] [角色数量]"
fun_srv_uninstall(){
    n=$3
    declare -A cfg
    check_node_cfg $@

    if [ ! -d ${cfg[root]}/dets ]; then
        ERR "目标路径\e[92m${cfg[root]}\e[0;0m不存在，或者不是游戏节点的安装目录，无法执行删除操作"
        exit 1
    fi

    if is_screen_exists ${cfg[nodename]}; then
        fun_srv_stop ${cfg[platform]} ${cfg[zone_id]}
    fi

    role_num=$(export MYSQL_PWD=${cfg['db_pass']} &&  mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -ss -e"select count(*) from role")
    if [ $? -ne 0 ]; then
        ERR "访问数据库失败，无法获取角色数量"
        exit 1
    fi
    if [ "$role_num" != "" ] && [ "${role_num//[[:space:]]/}" = "${n//[[:space:]]/}" ]; then
        INFO "正在删除数据库..."
        export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -e"drop database ${cfg['db_name']}"
        if [ $? -ne 0 ]; then
            ERR "访问数据库失败，无法删除数据库，如需继续请手动操作"
            exit 1
        fi
        INFO "正在删除安装目录..."
        rm -rf ${cfg[root]}
        INFO "节点\e[92m${cfg[nodename]}\e[0;0m已经删除"
    else
        ERR "参数中必须带有当前节点的角色数量，角色数量为[\e[92m${role_num}\e[0;0m]"
    fi
}



# 检查并补全节点配置信息
# 调用前先定义关联数组cfg: declare -A cfg
check_node_cfg(){
    local p=$1
    local z=$2
    if [ "$p" = "" ] || [ "$z" = "" ]; then
        ERR "参数中需要带有平台标识和区号"
        exit 1
    fi
    if ! is_integer $z; then
        ERR "参数区号必须为小于100的整数"
        exit 1
    fi
    if [ "$z" = "0" ] || [ "$p" = 'center' ] || [ "$p" = 'devcenter' ] || [ "$p" = 'twcenter' ] || [ "$p" = 'twdevcenter' ] || [ "$p" = 'hcenter' ]; then
        cfg[type]="center"
    else
        if [ "$p" = 'cloud' ] || [ "$p" = 'twcloud' ] || [ "$p" = 'twdevcloud' ] || [ "$p" = 'hcloud' ] ; then
            cfg[type]="cloud"
        else
            cfg[type]="zone"
        fi
    fi

    cfg[root]=${ZONE_BASE}/${GAME_CODE}_${p}_${z}
    cfg[code_path]="${ROOT}"
    cfg[nodename]="${GAME_CODE}_${p}_${z}@${HOST}"
    cfg[nodename2]="${GAME_CODE}_${p}_${z}"
    cfg[platform]=$p
    cfg[zone_id]=$z
#    cfg[combine]="{"\"${p}\"","${z}"}"
    cfg[host]="${HOST}"
    cfg[ip]="${HOST}"
    cfg[port]=$(($PORT_OFFSET+$z))
    cfg[cookie]=${ERL_COOKIE}
    cfg[srv_key]="45a92f431938ba5f90b8d83779e87318"
    cfg[zone_name]="${GAME_CODE}开发服${z}"
    cfg[lang]="zh_CN"
    cfg[fcm]="0"
    cfg[open_time]="1420713826"
    cfg[srv_open_time]="1420713826"
    cfg[open_time_test]="1420713826"
    cfg[merge_time]="0"
    cfg[merge_index]="0"
    cfg[pre_merge_time]="0"
    cfg[realmed]="0"
    cfg[website]="http://xianxia.syg"
    cfg[ver]="v1"
    cfg[center_node]=${GAME_CODE}_center_0@${HOST}
    cfg[db_host]=$DB_HOST
    cfg[db_port]=$DB_PORT
    cfg[db_user]=$DB_USER
    cfg[db_pass]=$DB_PASS
    cfg[db_name]=${GAME_CODE}_${p}_${z}
    cfg[db_conn_min]=10
    cfg[db_conn_max]=20
    cfg[need_register]=0
    cfg[group_id]=0
    cfg[is_main]=0
    cfg[is_maintain]=0
    cfg[flume_host_group]=0
}


DOC[srv_shell]="进入游戏服务器控制台(screen)，参数:[平台标识] [区号]"
fun_srv_shell(){
    if $(in_cygwin); then
        ERR "cygwin下不支持此命令"
        exit
    fi
    declare -A cfg
    check_node_cfg $@
    if ! is_screen_exists ${cfg[nodename]}; then
        ERR "节点\e[92m${cfg[nodename]}\e[0;0m似乎没有启动，无法进入控制台"
        exit 1
    fi
    screen -r ${cfg[nodename]}
}


DOC[srv_truncate]="清档, 参数:[平台标识] [区号] [角色数量]"
fun_srv_truncate(){
    n=$3
    declare -A cfg
    check_node_cfg $@

    role_num=$(export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -ss -e"select count(*) from role")
    if [ $? -ne 0 ]; then
        ERR "访问数据库失败，无法获取角色数量"
        exit 1
    fi
    if [ "$role_num" != "" ] && [ "${role_num//[[:space:]]/}" = "${n//[[:space:]]/}" ]; then
        if is_screen_exists ${cfg[nodename]}; then
            fun_srv_stop ${cfg[platform]} ${cfg[zone_id]}
        fi
        INFO "正在清档中..."
        # 排除列表，注意在排除列表外的所有表将会被清空
        # sys_notice_board=全服邮件表  sys_ip_white_list=IP白名单表  sys_notice_board2=系统公告表  sys_notice_scroll=滚屏公告表  sys_account_white_list=登陆白名单表
        exclude=( "sys_notice_board" "sys_ip_white_list" "sys_notice_board2" "sys_notice_scroll" "sys_account_white_list" )
        tabs=( $(export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -ss -e"show tables") )
        for v in ${tabs[@]}; do
            flag=0
            for v1 in ${exclude[@]}; do
                if [ "$v" = "$v1" ]; then
                    flag=1
                fi
            done
            if [ $flag = 0 ]; then
                sql="${sql} truncate table ${v};"
            fi
        done
        export MYSQL_PWD=${cfg['db_pass']} && mysql -h${cfg['db_host']} -P${cfg['db_port']} -u${cfg['db_user']} -D${cfg['db_name']} -ss -e"${sql}"
        if [ $? -ne 0 ]; then
            ERR "访问数据库失败，无法删除数据库，如需继续请手动操作"
            exit 1
        fi
        rm -f ${cfg[root]}/dets/*.dets
        rm -rf ${cfg[root]}/log
        rm -rf ${cfg[root]}/log_file
        mkdir -p ${cfg[root]}/log/pack
        mkdir -p ${cfg[root]}/log
        mkdir -p ${cfg[root]}/log_file
        rm -rf ${cfg[root]}/screenlog.0
        INFO "清档完成..."
    else
        ERR "参数中必须带有当前节点的角色数量，角色数量为[\e[92m${role_num}\e[0;0m]"
    fi
}